home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
DELPHI32
/
EDIT_UTL
/
LINKEDIT
/
LINKEDIT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-06-25
|
9KB
|
311 lines
unit linkedit;
{ Copyright 1996 - Vanguard Computer Services Pty Ltd, Jim Wowchuk
Portions copyrighted by Borland International
You are permitted to use, copy and adapt this code providing
doing so does not violate any other existing copyrights and
you do not attempt to remove, diminish or restrict the copyrights
of others that have provided this for you.
}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TlinkStyle = (lsNormal, lsEllipsis);
TLinkEdit = class(TCustomEdit)
private
{ Private declarations }
fButtonWidth : integer;
fLinkStyle : TLinkStyle;
fPressed : boolean;
fTracking : boolean;
fOnButtonClick : TNotifyEvent;
procedure StopTracking;
procedure SetLinkStyle(Value: TLinkStyle);
procedure TrackButton(X,Y: Integer);
procedure WMPaint(var Message: TWMPaint); message wm_Paint;
procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
protected
{ Protected declarations }
procedure BoundsChanged;
procedure EditButtonClick;
procedure CreateParams(var Params: TCreateParams); override;
procedure DoEnter; override;
procedure DoExit; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure PaintWindow(DC: HDC); override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property AutoSelect;
property AutoSize;
property BorderStyle;
property CharCase;
property Color;
property Ctl3D;
property DragCursor;
property DragMode;
property Enabled;
property Font;
property HideSelection;
property LinkStyle: TLinkStyle read fLinkStyle write SetLinkStyle default lsNormal;
property MaxLength;
property OEMConvert;
property ParentColor;
property ParentCtl3D;
property ParentFont;
property ParentShowHint;
property PasswordChar;
property PopupMenu;
property ReadOnly;
property ShowHint;
property TabOrder;
property TabStop;
property Text;
property Visible;
property OnButtonClick : TNotifyEvent read fOnButtonClick write fOnButtonClick;
property OnChange;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDrag;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('abaCIS', [TLinkEdit]);
end;
constructor TLinkEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
fButtonWidth := GetSystemMetrics(SM_CXVSCROLL);
fLinkStyle := lsNormal;
end; // Create
destructor TLinkEdit.Destroy;
begin
inherited Destroy;
end; // Destroy
procedure TLinkEdit.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
{ in order to use the EM_SETRECT later, we must make the edit control
a type MULTILINE }
with Params do
begin
Style := Style or ES_MULTILINE;
end;
end; // CreateParams
procedure TLinkEdit.BoundsChanged;
var
R: TRect;
begin
{ Determine the size of the text area in the control - it will
be smaller by the width of the button if one is present }
SetRect(R, 0, 0, ClientWidth - 2, ClientHeight + 1); // +1 is workaround for windows paint bug
if (fLinkStyle <> lsNormal) and focused then Dec(R.Right, fButtonWidth);
SendMessage(Handle, EM_SETRECT, 0, LongInt(@R));
Repaint;
end; // BoundsChanged
procedure TLinkEdit.SetLinkStyle(Value: TLinkStyle);
begin
{ if the link style is different then change it,
remember to redraw it if the control is currently
focused }
if Value = fLinkStyle then Exit;
fLinkStyle := Value;
if not HandleAllocated then exit;
if focused or (csDesigning in ComponentState) then
BoundsChanged;
end; // SetLinkStyle
procedure TLinkEdit.EditButtonClick;
begin
if Assigned(fOnButtonClick) then fOnButtonClick(Self);
end; // EditButtonClick
procedure TLinkEdit.WMPaint(var Message: TWMPaint);
begin
PaintHandler(Message)
end; // WMPaint
procedure TLinkEdit.WMSetCursor(var Msg: TWMSetCursor);
var
P: TPoint;
begin
{ Normally, the Edit control changes the Cursor to an I-bar when over
the control. We need to set it back to an arrow when over the button }
if (fLinkStyle <> lsNormal)
and PtInRect(Rect(Width - FButtonWidth - 4, 0, ClientWidth, ClientHeight), ScreenToClient(P)) then
begin
GetCursorPos(P);
Windows.SetCursor(LoadCursor(0, idc_Arrow));
end
else
inherited;
end; // WMSetCursor
procedure TLinkEdit.KeyDown(var Key: Word; Shift: TShiftState);
var
Msg: TMsg;
begin
{ simulate the mouse pressing the ellipsis button from the
keyboard by the user pressing CTRL+ENTER }
if (fLinkStyle = lsEllipsis)
and (Key = VK_RETURN)
and (Shift = [ssCtrl]) then
begin
EditButtonClick;
PeekMessage(Msg, Handle, WM_CHAR, WM_CHAR, PM_REMOVE);
end
else
inherited KeyDown(Key, Shift);
end; // KeyDown
procedure TLinkEdit.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
WasPressed: Boolean;
begin
{ if the mouse was released (after being pressed) on the button
then perform its associated action }
WasPressed := fPressed;
StopTracking;
if (Button = mbLeft) and (fLinkStyle = lsEllipsis) and WasPressed then
EditButtonClick;
inherited MouseUp(Button, Shift, X, Y);
end;
procedure TLinkEdit.TrackButton(X,Y: Integer);
var
NewState: Boolean;
R: TRect;
begin
{ Check if thhe position passed is over the area of the button -
if so then set the state to pressed and redraw the depressed
button }
SetRect(R, ClientWidth - fButtonWidth, 0, ClientWidth, ClientHeight);
NewState := PtInRect(R, Point(X, Y));
if fPressed <> NewState then
begin
fPressed := NewState;
InvalidateRect(Handle, @R, False);
end;
end; // TrackButton
procedure TLinkEdit.PaintWindow(DC: HDC);
var
R: TRect;
Flags: Integer;
W: Integer;
begin
{ here's where we draw the little elipsis button when necessary -
most times it is normal (raised) state, but sometimes it is pressed }
if (fLinkStyle <> lsNormal) and (focused or (csDesigning in ComponentState)) then
begin
SetRect(R, ClientWidth - fButtonWidth, 0, ClientWidth, ClientHeight);
Flags := 0;
if FPressed then
Flags := BF_FLAT;
DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_MIDDLE or Flags);
Flags := ((R.Right - R.Left) shr 1) - 1 + Ord(fPressed);
W := Height shr 3;
if W = 0 then W := 1;
PatBlt(DC, R.Left + Flags, R.Top + Flags, W, W, BLACKNESS);
PatBlt(DC, R.Left + Flags - (W * 2), R.Top + Flags, W, W, BLACKNESS);
PatBlt(DC, R.Left + Flags + (W * 2), R.Top + Flags, W, W, BLACKNESS);
ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
end;
inherited PaintWindow(DC);
end; // PaintWindow
procedure TLinkEdit.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
{ Not only must you press the button with the mouse, but it must be
released over the same button. If the button has been pressed, we
need to redraw it depressed, then track the mouse movements to see
if the user moves off it before releasing. }
if (Button = mbLeft) and (fLinkStyle <> lsNormal) and focused
and PtInRect(Rect(Width - fButtonWidth, 0, Width, Height), Point(X,Y)) then
begin
MouseCapture := True;
FTracking := True;
TrackButton(X, Y);
end;
inherited MouseDown(Button, Shift, X, Y);
end; // MouseDown
procedure TLinkEdit.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
{ if we are tracking the mouse, the mouse must have been pressed over
the button part of the control. Check to see we are still over it. }
if fTracking then
TrackButton(X, Y);
inherited MouseMove(Shift, X, Y);
end; // MouseMove
procedure TLinkEdit.StopTracking;
begin
{ we are finished tracking the mouse over the control. Reset everything }
if FTracking then
begin
TrackButton(-1, -1);
FTracking := False;
MouseCapture := False;
end;
end; // StopTracking;
procedure TLinkEdit.DoEnter;
begin
{ In use the elipsis button is only shown when we the control has focus }
if (fLinkStyle <> lsNormal)
then BoundsChanged;
inherited DoEnter;
end; // DoEnter
procedure TLinkEdit.DoExit;
begin
{ Remove the elipsis button (if present) when we lose focus }
if (fLinkStyle <> lsNormal)
then BoundsChanged;
inherited DoExit;
end;
end.